/*
 *  Copyright 2003 by Spectrum Digital Incorporated.
 *  All rights reserved. Property of Spectrum Digital Incorporated.
 */

/*
 *  ======== evmdm642_fpgaLoad.c ========
 *  EVMDM642_fpgaLoad() implementation
 */

#include <csl.h>
#include <csl_gpio.h>

#include "evmdm642.h"

#define FPGA_DIN     GPIO_PIN2
#define FPGA_CCLK    GPIO_PIN1
#define FPGA_PROG    GPIO_PIN0
#define FPGA_INIT    GPIO_PIN6

static void fpgawrite(GPIO_Handle hGPIO, Uint16 data)
{
    Uint32 i;
    
    for (i = 0; i < 8; i++)
    {
        /* Clock low */
        GPIO_pinWrite(hGPIO, FPGA_CCLK, 0);
        
        /* Output data */
        GPIO_pinWrite(hGPIO, FPGA_DIN, (data >> 7) & 1);
        asm(" nop 9");
        
        /* Clock high */
        GPIO_pinWrite(hGPIO, FPGA_CCLK, 1);
        asm(" nop 3");
        
        /* Set up for next bit */
        data = data << 1;
    }
}
 
void EVMDM642_fpgaLoad(Uint32 fpgaaddr)
{
    Uint8 *pdata;
    Uint32 i, j;
    
    /* Set internal pin mux to GPIOs */
    GPIO_pinEnable(EVMDM642_GPIO_hGPIO, FPGA_CCLK | FPGA_DIN);
    
    /* Set direction - CCLK, PROG and DIN output, INIT input */
    GPIO_pinDirection(EVMDM642_GPIO_hGPIO, FPGA_CCLK | FPGA_PROG | FPGA_DIN, GPIO_OUTPUT);
    GPIO_pinDirection(EVMDM642_GPIO_hGPIO, FPGA_INIT, GPIO_INPUT);
    
    /* Set PROG low, CCLK high */
    GPIO_pinWrite(EVMDM642_GPIO_hGPIO, FPGA_CCLK, 1);
    GPIO_pinWrite(EVMDM642_GPIO_hGPIO, FPGA_PROG, 0);

    /* Wait for INIT to go low */
    while (GPIO_pinRead(EVMDM642_GPIO_hGPIO, FPGA_INIT) == 1);

    /* Short delay then drive PROG high */
    for (i = 0; i < 1000; i++);
    GPIO_pinWrite(EVMDM642_GPIO_hGPIO, FPGA_PROG, 1);
    
    /* Wait for INIT to go high */
    while (GPIO_pinRead(EVMDM642_GPIO_hGPIO, FPGA_INIT) == 0);

    /* Write data */
    pdata = (Uint8 *)fpgaaddr;
    for (i = 0; i < EVMDM642_FPGALEN; i++)
    {
        fpgawrite(EVMDM642_GPIO_hGPIO, *pdata++);
    }

    /* Clock the FPGA to finish the initialization */
    for (i = 0; i < 8; i++)
    {
        /* Clock low */
        GPIO_pinWrite(EVMDM642_GPIO_hGPIO, FPGA_CCLK, 0);
        for (j = 0; j < 100; j++);
        
        /* Clock high */
        GPIO_pinWrite(EVMDM642_GPIO_hGPIO, FPGA_CCLK, 1);
        for (j = 0; j < 100; j++);
    }
    
    /* Toggle FPGA soft reset */
    EVMDM642_rset(EVMDM642_OSDCTRL, EVMDM642_rget(EVMDM642_OSDCTRL) | 0x01);
    for (i = 0; i < 1000; i++);
    EVMDM642_rset(EVMDM642_OSDCTRL, EVMDM642_rget(EVMDM642_OSDCTRL) & ~0x01);
}

